home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / gawk-3.000 / gawk-3 / gawk-3.0.0 / eval.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-31  |  36.2 KB  |  1,421 lines

  1. /*
  2.  * eval.c - gawk parse tree interpreter 
  3.  */
  4.  
  5. /* 
  6.  * Copyright (C) 1986, 1988, 1989, 1991-1995 the Free Software Foundation, Inc.
  7.  * 
  8.  * This file is part of GAWK, the GNU implementation of the
  9.  * AWK Programming Language.
  10.  * 
  11.  * GAWK is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  * 
  16.  * GAWK is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  * 
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
  24.  */
  25.  
  26. #include "awk.h"
  27.  
  28. extern double pow P((double x, double y));
  29. extern double modf P((double x, double *yp));
  30. extern double fmod P((double x, double y));
  31.  
  32. static int eval_condition P((NODE *tree));
  33. static NODE *op_assign P((NODE *tree));
  34. static NODE *func_call P((NODE *name, NODE *arg_list));
  35. static NODE *match_op P((NODE *tree));
  36.  
  37. #if __GNUC__ < 2
  38. NODE *_t;        /* used as a temporary in macros */
  39. #endif
  40. #ifdef MSDOS
  41. double _msc51bug;    /* to get around a bug in MSC 5.1 */
  42. #endif
  43. NODE *ret_node;
  44. int OFSlen;
  45. int ORSlen;
  46. int OFMTidx;
  47. int CONVFMTidx;
  48.  
  49. /* Macros and variables to save and restore function and loop bindings */
  50. /*
  51.  * the val variable allows return/continue/break-out-of-context to be
  52.  * caught and diagnosed
  53.  */
  54. #define PUSH_BINDING(stack, x, val) (memcpy((char *)(stack), (char *)(x), sizeof(jmp_buf)), val++)
  55. #define RESTORE_BINDING(stack, x, val) (memcpy((char *)(x), (char *)(stack), sizeof(jmp_buf)), val--)
  56.  
  57. static jmp_buf loop_tag;        /* always the current binding */
  58. static int loop_tag_valid = FALSE;    /* nonzero when loop_tag valid */
  59. static int func_tag_valid = FALSE;
  60. static jmp_buf func_tag;
  61. extern int exiting, exit_val;
  62.  
  63. /*
  64.  * This table is used by the regexp routines to do case independant
  65.  * matching. Basically, every ascii character maps to itself, except
  66.  * uppercase letters map to lower case ones. This table has 256
  67.  * entries, for ISO 8859-1. Note also that if the system this
  68.  * is compiled on doesn't use 7-bit ascii, casetable[] should not be
  69.  * defined to the linker, so gawk should not load.
  70.  *
  71.  * Do NOT make this array static, it is used in several spots, not
  72.  * just in this file.
  73.  */
  74. #if 'a' == 97    /* it's ascii */
  75. char casetable[] = {
  76.     '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
  77.     '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
  78.     '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
  79.     '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
  80.     /* ' '     '!'     '"'     '#'     '$'     '%'     '&'     ''' */
  81.     '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
  82.     /* '('     ')'     '*'     '+'     ','     '-'     '.'     '/' */
  83.     '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
  84.     /* '0'     '1'     '2'     '3'     '4'     '5'     '6'     '7' */
  85.     '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
  86.     /* '8'     '9'     ':'     ';'     '<'     '='     '>'     '?' */
  87.     '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
  88.     /* '@'     'A'     'B'     'C'     'D'     'E'     'F'     'G' */
  89.     '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  90.     /* 'H'     'I'     'J'     'K'     'L'     'M'     'N'     'O' */
  91.     '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  92.     /* 'P'     'Q'     'R'     'S'     'T'     'U'     'V'     'W' */
  93.     '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  94.     /* 'X'     'Y'     'Z'     '['     '\'     ']'     '^'     '_' */
  95.     '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
  96.     /* '`'     'a'     'b'     'c'     'd'     'e'     'f'     'g' */
  97.     '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  98.     /* 'h'     'i'     'j'     'k'     'l'     'm'     'n'     'o' */
  99.     '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  100.     /* 'p'     'q'     'r'     's'     't'     'u'     'v'     'w' */
  101.     '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  102.     /* 'x'     'y'     'z'     '{'     '|'     '}'     '~' */
  103.     '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
  104. #ifndef USE_PURE_ASCII
  105.     '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
  106.     '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
  107.     '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
  108.     '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
  109.     '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
  110.     '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
  111.     '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
  112.     '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
  113.     '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  114.     '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  115.     '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\327',
  116.     '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\337',
  117.     '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  118.     '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  119.     '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  120.     '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
  121. #else
  122.     '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
  123.     '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
  124.     '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
  125.     '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
  126.     '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
  127.     '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
  128.     '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
  129.     '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
  130.     '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
  131.     '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
  132.     '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
  133.     '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
  134.     '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  135.     '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  136.     '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  137.     '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
  138. #endif
  139. };
  140. #else
  141. #include "You lose. You will need a translation table for your character set."
  142. #endif
  143.  
  144. /*
  145.  * interpret:
  146.  * Tree is a bunch of rules to run. Returns zero if it hit an exit()
  147.  * statement 
  148.  */
  149. int
  150. interpret(tree)
  151. register NODE *volatile tree;
  152. {
  153.     jmp_buf volatile loop_tag_stack; /* shallow binding stack for loop_tag */
  154.     static jmp_buf rule_tag; /* tag the rule currently being run, for NEXT
  155.                   * and EXIT statements.  It is static because
  156.                   * there are no nested rules */
  157.     register NODE *volatile t = NULL;    /* temporary */
  158.     NODE **volatile lhs;    /* lhs == Left Hand Side for assigns, etc */
  159.     NODE *volatile stable_tree;
  160.     int volatile traverse = TRUE;    /* True => loop thru tree (Node_rule_list) */
  161.  
  162.     /* avoid false source indications */
  163.     source = NULL;
  164.     sourceline = 0;
  165.  
  166.     if (tree == NULL)
  167.         return 1;
  168.     sourceline = tree->source_line;
  169.     source = tree->source_file;
  170.     switch (tree->type) {
  171.     case Node_rule_node:
  172.         traverse = FALSE;  /* False => one for-loop iteration only */
  173.         /* FALL THROUGH */
  174.     case Node_rule_list:
  175.         for (t = tree; t != NULL; t = t->rnode) {
  176.             if (traverse)
  177.                 tree = t->lnode;
  178.             sourceline = tree->source_line;
  179.             source = tree->source_file;
  180.             switch (setjmp(rule_tag)) {
  181.             case 0:    /* normal non-jump */
  182.                 /* test pattern, if any */
  183.                 if (tree->lnode == NULL ||
  184.                     eval_condition(tree->lnode))
  185.                     (void) interpret(tree->rnode);
  186.                 break;
  187.             case TAG_CONTINUE:    /* NEXT statement */
  188.                 return 1;
  189.             case TAG_BREAK:
  190.                 return 0;
  191.             default:
  192.                 cant_happen();
  193.             }
  194.             if (! traverse)     /* case Node_rule_node */
  195.                 break;        /* don't loop */
  196.         }
  197.         break;
  198.  
  199.     case Node_statement_list:
  200.         for (t = tree; t != NULL; t = t->rnode)
  201.             (void) interpret(t->lnode);
  202.         break;
  203.  
  204.     case Node_K_if:
  205.         if (eval_condition(tree->lnode))
  206.             (void) interpret(tree->rnode->lnode);
  207.         else
  208.             (void) interpret(tree->rnode->rnode);
  209.         break;
  210.  
  211.     case Node_K_while:
  212.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  213.  
  214.         stable_tree = tree;
  215.         while (eval_condition(stable_tree->lnode)) {
  216.             switch (setjmp(loop_tag)) {
  217.             case 0:    /* normal non-jump */
  218.                 (void) interpret(stable_tree->rnode);
  219.                 break;
  220.             case TAG_CONTINUE:    /* continue statement */
  221.                 break;
  222.             case TAG_BREAK:    /* break statement */
  223.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  224.                 return 1;
  225.             default:
  226.                 cant_happen();
  227.             }
  228.         }
  229.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  230.         break;
  231.  
  232.     case Node_K_do:
  233.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  234.         stable_tree = tree;
  235.         do {
  236.             switch (setjmp(loop_tag)) {
  237.             case 0:    /* normal non-jump */
  238.                 (void) interpret(stable_tree->rnode);
  239.                 break;
  240.             case TAG_CONTINUE:    /* continue statement */
  241.                 break;
  242.             case TAG_BREAK:    /* break statement */
  243.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  244.                 return 1;
  245.             default:
  246.                 cant_happen();
  247.             }
  248.         } while (eval_condition(stable_tree->lnode));
  249.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  250.         break;
  251.  
  252.     case Node_K_for:
  253.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  254.         (void) interpret(tree->forloop->init);
  255.         stable_tree = tree;
  256.         while (eval_condition(stable_tree->forloop->cond)) {
  257.             switch (setjmp(loop_tag)) {
  258.             case 0:    /* normal non-jump */
  259.                 (void) interpret(stable_tree->lnode);
  260.                 /* fall through */
  261.             case TAG_CONTINUE:    /* continue statement */
  262.                 (void) interpret(stable_tree->forloop->incr);
  263.                 break;
  264.             case TAG_BREAK:    /* break statement */
  265.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  266.                 return 1;
  267.             default:
  268.                 cant_happen();
  269.             }
  270.         }
  271.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  272.         break;
  273.  
  274.     case Node_K_arrayfor:
  275.         {
  276.         volatile struct search l;    /* For array_for */
  277.         Func_ptr after_assign = NULL;
  278.  
  279. #define hakvar forloop->init
  280. #define arrvar forloop->incr
  281.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  282.         lhs = get_lhs(tree->hakvar, &after_assign);
  283.         t = tree->arrvar;
  284.         if (t->type == Node_param_list)
  285.             t = stack_ptr[t->param_cnt];
  286.         stable_tree = tree;
  287.         if ((t->flags & SCALAR) != 0)
  288.             fatal("attempt to use scalar as array");
  289.         for (assoc_scan(t, (struct search *)&l);
  290.              l.retval;
  291.              assoc_next((struct search *)&l)) {
  292.             unref(*((NODE **) lhs));
  293.             *lhs = dupnode(l.retval);
  294.             if (after_assign)
  295.                 (*after_assign)();
  296.             switch (setjmp(loop_tag)) {
  297.             case 0:
  298.                 (void) interpret(stable_tree->lnode);
  299.             case TAG_CONTINUE:
  300.                 break;
  301.  
  302.             case TAG_BREAK:
  303.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  304.                 return 1;
  305.             default:
  306.                 cant_happen();
  307.             }
  308.         }
  309.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  310.         break;
  311.         }
  312.  
  313.     case Node_K_break:
  314.         if (! loop_tag_valid) {
  315.             /*
  316.              * Old AT&T nawk treats break outside of loops like
  317.              * next. New ones catch it at parse time. Allow it if
  318.              * do_traditional is on, and complain if lint.
  319.              */
  320.             static int warned = FALSE;
  321.  
  322.             if (do_lint && ! warned) {
  323.                 warning("use of `break' outside a loop is not portable");
  324.                 warned = TRUE;
  325.             }
  326.             if (! do_traditional || do_posix)
  327.                 fatal("use of `break' outside a loop is not allowed");
  328.             longjmp(rule_tag, TAG_CONTINUE);
  329.         } else
  330.             longjmp(loop_tag, TAG_BREAK);
  331.         break;
  332.  
  333.     case Node_K_continue:
  334.         if (! loop_tag_valid) {
  335.             /*
  336.              * Old AT&T nawk treats continue outside of loops like
  337.              * next. New ones catch it at parse time. Allow it if
  338.              * do_traditional is on, and complain if lint.
  339.              */
  340.             static int warned = FALSE;
  341.  
  342.             if (do_lint && ! warned) {
  343.                 warning("use of `continue' outside a loop is not portable");
  344.                 warned = TRUE;
  345.             }
  346.             if (! do_traditional || do_posix)
  347.                 fatal("use of `continue' outside a loop is not allowed");
  348.             longjmp(rule_tag, TAG_CONTINUE);
  349.         } else
  350.             longjmp(loop_tag, TAG_CONTINUE);
  351.         break;
  352.  
  353.     case Node_K_print:
  354.         do_print(tree);
  355.         break;
  356.  
  357.     case Node_K_printf:
  358.         do_printf(tree);
  359.         break;
  360.  
  361.     case Node_K_delete:
  362.         if (tree->rnode != NULL)    /* delete array */
  363.             do_delete(tree->lnode, tree->rnode);
  364.         else
  365.             assoc_clear(tree->lnode);
  366.         break;
  367.  
  368.     case Node_K_next:
  369.         longjmp(rule_tag, TAG_CONTINUE);
  370.         break;
  371.  
  372.     case Node_K_nextfile:
  373.         do_nextfile();
  374.         break;
  375.  
  376.     case Node_K_exit:
  377.         /*
  378.          * In A,K,&W, p. 49, it says that an exit statement "...
  379.          * causes the program to behave as if the end of input had
  380.          * occurred; no more input is read, and the END actions, if
  381.          * any are executed." This implies that the rest of the rules
  382.          * are not done. So we immediately break out of the main loop.
  383.          */
  384.         exiting = TRUE;
  385.         if (tree->lnode != NULL) {
  386.             t = tree_eval(tree->lnode);
  387.             exit_val = (int) force_number(t);
  388.             free_temp(t);
  389.         }
  390.         longjmp(rule_tag, TAG_BREAK);
  391.         break;
  392.  
  393.     case Node_K_return:
  394.         t = tree_eval(tree->lnode);
  395.         ret_node = dupnode(t);
  396.         free_temp(t);
  397.         longjmp(func_tag, TAG_RETURN);
  398.         break;
  399.  
  400.     default:
  401.         /*
  402.          * Appears to be an expression statement.  Throw away the
  403.          * value. 
  404.          */
  405.         if (do_lint && tree->type == Node_var)
  406.             warning("statement has no effect");
  407.         t = tree_eval(tree);
  408.         free_temp(t);
  409.         break;
  410.     }
  411.     return 1;
  412. }
  413.  
  414. /* r_tree_eval --- evaluate a subtree */
  415.  
  416. NODE *
  417. r_tree_eval(tree, iscond)
  418. register NODE *tree;
  419. int iscond;
  420. {
  421.     register NODE *r, *t1, *t2;    /* return value & temporary subtrees */
  422.     register NODE **lhs;
  423.     register int di;
  424.     AWKNUM x, x1, x2;
  425.     long lx;
  426. #ifdef _CRAY
  427.     long lx2;
  428. #endif
  429.     char namebuf[100];
  430.  
  431. #ifdef DEBUG
  432.     if (tree == NULL)
  433.         return Nnull_string;
  434.     else if (tree->type == Node_val) {
  435.         if (tree->stref <= 0)
  436.             cant_happen();
  437.         return tree;
  438.     } else if (tree->type == Node_var) {
  439.         if (tree->var_value->stref <= 0)
  440.             cant_happen();
  441.         return tree->var_value;
  442.     }
  443. #endif
  444.  
  445.     if (tree->type == Node_param_list) {
  446.         int paramnum = tree->param_cnt + 1;
  447.  
  448.         tree = stack_ptr[tree->param_cnt];
  449.         if (tree == NULL)
  450.             return Nnull_string;
  451.         sprintf(namebuf, "parameter #%d", paramnum);
  452.         tree->vname = namebuf;
  453.     }
  454.  
  455.     switch (tree->type) {
  456.     case Node_var:
  457.         return tree->var_value;
  458.  
  459.     case Node_and:
  460.         return tmp_number((AWKNUM) (eval_condition(tree->lnode)
  461.                         && eval_condition(tree->rnode)));
  462.  
  463.     case Node_or:
  464.         return tmp_number((AWKNUM) (eval_condition(tree->lnode)
  465.                         || eval_condition(tree->rnode)));
  466.  
  467.     case Node_not:
  468.         return tmp_number((AWKNUM) ! eval_condition(tree->lnode));
  469.  
  470.         /* Builtins */
  471.     case Node_builtin:
  472.         return (*tree->proc)(tree->subnode);
  473.  
  474.     case Node_K_getline:
  475.         return (do_getline(tree));
  476.  
  477.     case Node_in_array:
  478.         return tmp_number((AWKNUM) in_array(tree->lnode, tree->rnode));
  479.  
  480.     case Node_func_call:
  481.         return func_call(tree->rnode, tree->lnode);
  482.  
  483.         /* unary operations */
  484.     case Node_NR:
  485.     case Node_FNR:
  486.     case Node_NF:
  487.     case Node_FIELDWIDTHS:
  488.     case Node_FS:
  489.     case Node_RS:
  490.     case Node_field_spec:
  491.     case Node_subscript:
  492.     case Node_IGNORECASE:
  493.     case Node_OFS:
  494.     case Node_ORS:
  495.     case Node_OFMT:
  496.     case Node_CONVFMT:
  497.         lhs = get_lhs(tree, (Func_ptr *) NULL);
  498.         return *lhs;
  499.  
  500.     case Node_var_array:
  501.         fatal("attempt to use array `%s' in a scalar context",
  502.             tree->vname);
  503.  
  504.     case Node_unary_minus:
  505.         t1 = tree_eval(tree->subnode);
  506.         x = -force_number(t1);
  507.         free_temp(t1);
  508.         return tmp_number(x);
  509.  
  510.     case Node_cond_exp:
  511.         if (eval_condition(tree->lnode))
  512.             return tree_eval(tree->rnode->lnode);
  513.         return tree_eval(tree->rnode->rnode);
  514.  
  515.     case Node_match:
  516.     case Node_nomatch:
  517.     case Node_regex:
  518.         return match_op(tree);
  519.  
  520.     case Node_func:
  521.         fatal("function `%s' called with space between name and (,\n%s",
  522.             tree->lnode->param,
  523.             "or used in other expression context");
  524.  
  525.         /* assignments */
  526.     case Node_assign:
  527.         {
  528.         Func_ptr after_assign = NULL;
  529.  
  530.         if (iscond && do_lint)
  531.             warning("assignment used in conditional context");
  532.         r = tree_eval(tree->rnode);
  533.         lhs = get_lhs(tree->lnode, &after_assign);
  534.         if (r != *lhs) {
  535.             NODE *save;
  536.  
  537.             save = *lhs;
  538.             *lhs = dupnode(r);
  539.             unref(save);
  540.         }
  541.         free_temp(r);
  542.         tree->lnode->flags |= SCALAR;
  543.         if (after_assign)
  544.             (*after_assign)();
  545.         return *lhs;
  546.         }
  547.  
  548.     case Node_concat:
  549.         {
  550.         NODE **treelist;
  551.         NODE **strlist;
  552.         NODE *save_tree;
  553.         register NODE **treep;
  554.         register NODE **strp;
  555.         register size_t len;
  556.         char *str;
  557.         register char *dest;
  558.         int count;
  559.  
  560.         /*
  561.          * This is an efficiency hack for multiple adjacent string
  562.          * concatenations, to avoid recursion and string copies.
  563.          *
  564.          * Node_concat trees grow downward to the left, so
  565.          * descend to lowest (first) node, accumulating nodes
  566.          * to evaluate to strings as we go.
  567.          */
  568.  
  569.         /*
  570.          * But first, no arbitrary limits. Count the number of
  571.          * nodes and malloc the treelist and strlist arrays.
  572.          * There will be count + 1 items to concatenate. We
  573.          * also leave room for an extra pointer at the end to
  574.          * use as a sentinel.  Thus, start count at 2.
  575.          */
  576.         save_tree = tree;
  577.         for (count = 2; tree && tree->type == Node_concat; tree = tree->lnode)
  578.             count++;
  579.         tree = save_tree;
  580.         emalloc(treelist, NODE **, sizeof(NODE *) * count, "tree_eval");
  581.         emalloc(strlist, NODE **, sizeof(NODE *) * count, "tree_eval");
  582.  
  583.         /* Now, here we go. */
  584.         treep = treelist;
  585.         while (tree && tree->type == Node_concat) {
  586.             *treep++ = tree->rnode;
  587.             tree = tree->lnode;
  588.         }
  589.         *treep = tree;
  590.         /*
  591.          * Now, evaluate to strings in LIFO order, accumulating
  592.          * the string length, so we can do a single malloc at the
  593.          * end.
  594.          */
  595.         strp = strlist;
  596.         len = 0;
  597.         while (treep >= treelist) {
  598.             *strp = force_string(tree_eval(*treep--));
  599.             len += (*strp)->stlen;
  600.             strp++;
  601.         }
  602.         *strp = NULL;
  603.         emalloc(str, char *, len+2, "tree_eval");
  604.         str[len] = str[len+1] = '\0';    /* for good measure */
  605.         dest = str;
  606.         strp = strlist;
  607.         while (*strp) {
  608.             memcpy(dest, (*strp)->stptr, (*strp)->stlen);
  609.             dest += (*strp)->stlen;
  610.             free_temp(*strp);
  611.             strp++;
  612.         }
  613.         r = make_str_node(str, len, ALREADY_MALLOCED);
  614.         r->flags |= TEMP;
  615.  
  616.         free(strlist);
  617.         free(treelist);
  618.         }
  619.         return r;
  620.  
  621.     /* other assignment types are easier because they are numeric */
  622.     case Node_preincrement:
  623.     case Node_predecrement:
  624.     case Node_postincrement:
  625.     case Node_postdecrement:
  626.     case Node_assign_exp:
  627.     case Node_assign_times:
  628.     case Node_assign_quotient:
  629.     case Node_assign_mod:
  630.     case Node_assign_plus:
  631.     case Node_assign_minus:
  632.         return op_assign(tree);
  633.     default:
  634.         break;    /* handled below */
  635.     }
  636.  
  637.     /* evaluate subtrees in order to do binary operation, then keep going */
  638.     t1 = tree_eval(tree->lnode);
  639.     t2 = tree_eval(tree->rnode);
  640.  
  641.     switch (tree->type) {
  642.     case Node_geq:
  643.     case Node_leq:
  644.     case Node_greater:
  645.     case Node_less:
  646.     case Node_notequal:
  647.     case Node_equal:
  648.         di = cmp_nodes(t1, t2);
  649.         free_temp(t1);
  650.         free_temp(t2);
  651.         switch (tree->type) {
  652.         case Node_equal:
  653.             return tmp_number((AWKNUM) (di == 0));
  654.         case Node_notequal:
  655.             return tmp_number((AWKNUM) (di != 0));
  656.         case Node_less:
  657.             return tmp_number((AWKNUM) (di < 0));
  658.         case Node_greater:
  659.             return tmp_number((AWKNUM) (di > 0));
  660.         case Node_leq:
  661.             return tmp_number((AWKNUM) (di <= 0));
  662.         case Node_geq:
  663.             return tmp_number((AWKNUM) (di >= 0));
  664.         default:
  665.             cant_happen();
  666.         }
  667.         break;
  668.     default:
  669.         break;    /* handled below */
  670.     }
  671.  
  672.     x1 = force_number(t1);
  673.     free_temp(t1);
  674.     x2 = force_number(t2);
  675.     free_temp(t2);
  676.     switch (tree->type) {
  677.     case Node_exp:
  678.         if ((lx = x2) == x2 && lx >= 0) {    /* integer exponent */
  679.             if (lx == 0)
  680.                 x = 1;
  681.             else if (lx == 1)
  682.                 x = x1;
  683.             else {
  684.                 /* doing it this way should be more precise */
  685.                 for (x = x1; --lx; )
  686.                     x *= x1;
  687.             }
  688.         } else
  689.             x = pow((double) x1, (double) x2);
  690.         return tmp_number(x);
  691.  
  692.     case Node_times:
  693.         return tmp_number(x1 * x2);
  694.  
  695.     case Node_quotient:
  696.         if (x2 == 0)
  697.             fatal("division by zero attempted");
  698. #ifdef _CRAY
  699.         /* special case for integer division, put in for Cray */
  700.         lx2 = x2;
  701.         if (lx2 == 0)
  702.             return tmp_number(x1 / x2);
  703.         lx = (long) x1 / lx2;
  704.         if (lx * x2 == x1)
  705.             return tmp_number((AWKNUM) lx);
  706.         else
  707. #endif
  708.             return tmp_number(x1 / x2);
  709.  
  710.     case Node_mod:
  711.         if (x2 == 0)
  712.             fatal("division by zero attempted in mod");
  713. #ifdef HAVE_FMOD
  714.         return tmp_number(fmod(x1, x2));
  715. #else    /* ! HAVE_FMOD */
  716.         (void) modf(x1 / x2, &x);
  717.         return tmp_number(x1 - x * x2);
  718. #endif    /* ! HAVE_FMOD */
  719.  
  720.     case Node_plus:
  721.         return tmp_number(x1 + x2);
  722.  
  723.     case Node_minus:
  724.         return tmp_number(x1 - x2);
  725.  
  726.     case Node_var_array:
  727.         fatal("attempt to use array `%s' in a scalar context",
  728.             tree->vname);
  729.  
  730.     default:
  731.         fatal("illegal type (%d) in tree_eval", tree->type);
  732.     }
  733.     return 0;
  734. }
  735.  
  736. /* eval_condition --- is TREE true or false? Returns 0==false, non-zero==true */
  737.  
  738. static int
  739. eval_condition(tree)
  740. register NODE *tree;
  741. {
  742.     register NODE *t1;
  743.     register int ret;
  744.  
  745.     if (tree == NULL)    /* Null trees are the easiest kinds */
  746.         return TRUE;
  747.     if (tree->type == Node_line_range) {
  748.         /*
  749.          * Node_line_range is kind of like Node_match, EXCEPT: the
  750.          * lnode field (more properly, the condpair field) is a node
  751.          * of a Node_cond_pair; whether we evaluate the lnode of that
  752.          * node or the rnode depends on the triggered word.  More
  753.          * precisely:  if we are not yet triggered, we tree_eval the
  754.          * lnode; if that returns true, we set the triggered word. 
  755.          * If we are triggered (not ELSE IF, note), we tree_eval the
  756.          * rnode, clear triggered if it succeeds, and perform our
  757.          * action (regardless of success or failure).  We want to be
  758.          * able to begin and end on a single input record, so this
  759.          * isn't an ELSE IF, as noted above.
  760.          */
  761.         if (! tree->triggered)
  762.             if (! eval_condition(tree->condpair->lnode))
  763.                 return FALSE;
  764.             else
  765.                 tree->triggered = TRUE;
  766.         /* Else we are triggered */
  767.         if (eval_condition(tree->condpair->rnode))
  768.             tree->triggered = FALSE;
  769.         return TRUE;
  770.     }
  771.  
  772.     /*
  773.      * Could just be J.random expression. in which case, null and 0 are
  774.      * false, anything else is true 
  775.      */
  776.  
  777.     t1 = m_tree_eval(tree, TRUE);
  778.     if (t1->flags & MAYBE_NUM)
  779.         (void) force_number(t1);
  780.     if (t1->flags & NUMBER)
  781.         ret = (t1->numbr != 0.0);
  782.     else
  783.         ret = (t1->stlen != 0);
  784.     free_temp(t1);
  785.     return ret;
  786. }
  787.  
  788. /* cmp_nodes --- compare two nodes, returning negative, 0, positive */
  789.  
  790. int
  791. cmp_nodes(t1, t2)
  792. register NODE *t1, *t2;
  793. {
  794.     register int ret;
  795.     register size_t len1, len2;
  796.     register int l;
  797.     int ldiff;
  798.  
  799.     if (t1 == t2)
  800.         return 0;
  801.     if (t1->flags & MAYBE_NUM)
  802.         (void) force_number(t1);
  803.     if (t2->flags & MAYBE_NUM)
  804.         (void) force_number(t2);
  805.     if ((t1->flags & NUMBER) && (t2->flags & NUMBER)) {
  806.         if (t1->numbr == t2->numbr)
  807.             return 0;
  808.         /* don't subtract, in case one or both are infinite */
  809.         else if (t1->numbr < t2->numbr)
  810.             return -1;
  811.         else
  812.             return 1;
  813.     }
  814.     (void) force_string(t1);
  815.     (void) force_string(t2);
  816.     len1 = t1->stlen;
  817.     len2 = t2->stlen;
  818.     ldiff = len1 - len2;
  819.     if (len1 == 0 || len2 == 0)
  820.         return ldiff;
  821.     l = (ldiff <= 0 ? len1 : len2);
  822.     if (IGNORECASE) {
  823.         register unsigned char *cp1 = (unsigned char *) t1->stptr;
  824.         register unsigned char *cp2 = (unsigned char *) t2->stptr;
  825.  
  826.         for (ret = 0; l-- > 0 && ret == 0; cp1++, cp2++)
  827.             ret = casetable[*cp1] - casetable[*cp2];
  828.     } else
  829.         ret = memcmp(t1->stptr, t2->stptr, l);
  830.     return (ret == 0 ? ldiff : ret);
  831. }
  832.  
  833. /* op_assign --- do +=, -=, etc. */
  834.  
  835. static NODE *
  836. op_assign(tree)
  837. register NODE *tree;
  838. {
  839.     AWKNUM rval, lval;
  840.     NODE **lhs;
  841.     AWKNUM t1, t2;
  842.     long ltemp;
  843.     NODE *tmp;
  844.     Func_ptr after_assign = NULL;
  845.  
  846.     lhs = get_lhs(tree->lnode, &after_assign);
  847.     lval = force_number(*lhs);
  848.  
  849.     /*
  850.      * Can't unref *lhs until we know the type; doing so
  851.      * too early breaks   x += x   sorts of things.
  852.      */
  853.     switch(tree->type) {
  854.     case Node_preincrement:
  855.     case Node_predecrement:
  856.         unref(*lhs);
  857.         *lhs = make_number(lval +
  858.                    (tree->type == Node_preincrement ? 1.0 : -1.0));
  859.         tree->lnode->flags |= SCALAR;
  860.         if (after_assign)
  861.             (*after_assign)();
  862.         return *lhs;
  863.  
  864.     case Node_postincrement:
  865.     case Node_postdecrement:
  866.         unref(*lhs);
  867.         *lhs = make_number(lval +
  868.                    (tree->type == Node_postincrement ? 1.0 : -1.0));
  869.         tree->lnode->flags |= SCALAR;
  870.         if (after_assign)
  871.             (*after_assign)();
  872.         return tmp_number(lval);
  873.     default:
  874.         break;    /* handled below */
  875.     }
  876.  
  877.     tmp = tree_eval(tree->rnode);
  878.     rval = force_number(tmp);
  879.     free_temp(tmp);
  880.  
  881.     /*
  882.      * Do this again; the lhs and the rhs could both be fields.
  883.      * Accessing the rhs could cause the lhs to have moved around.
  884.      * (Yet another special case. Gack.)
  885.      */
  886.     lhs = get_lhs(tree->lnode, &after_assign);
  887.  
  888.     unref(*lhs);
  889.     switch(tree->type) {
  890.     case Node_assign_exp:
  891.         if ((ltemp = rval) == rval) {    /* integer exponent */
  892.             if (ltemp == 0)
  893.                 *lhs = make_number((AWKNUM) 1);
  894.             else if (ltemp == 1)
  895.                 *lhs = make_number(lval);
  896.             else {
  897.                 /* doing it this way should be more precise */
  898.                 for (t1 = t2 = lval; --ltemp; )
  899.                     t1 *= t2;
  900.                 *lhs = make_number(t1);
  901.             }
  902.         } else
  903.             *lhs = make_number((AWKNUM) pow((double) lval, (double) rval));
  904.         break;
  905.  
  906.     case Node_assign_times:
  907.         *lhs = make_number(lval * rval);
  908.         break;
  909.  
  910.     case Node_assign_quotient:
  911.         if (rval == (AWKNUM) 0)
  912.             fatal("division by zero attempted in /=");
  913. #ifdef _CRAY
  914.         /* special case for integer division, put in for Cray */
  915.         ltemp = rval;
  916.         if (ltemp == 0) {
  917.             *lhs = make_number(lval / rval);
  918.             break;
  919.         }
  920.         ltemp = (long) lval / ltemp;
  921.         if (ltemp * lval == rval)
  922.             *lhs = make_number((AWKNUM) ltemp);
  923.         else
  924. #endif    /* _CRAY */
  925.             *lhs = make_number(lval / rval);
  926.         break;
  927.  
  928.     case Node_assign_mod:
  929.         if (rval == (AWKNUM) 0)
  930.             fatal("division by zero attempted in %=");
  931. #ifdef HAVE_FMOD
  932.         *lhs = make_number(fmod(lval, rval));
  933. #else    /* ! HAVE_FMOD */
  934.         (void) modf(lval / rval, &t1);
  935.         t2 = lval - rval * t1;
  936.         *lhs = make_number(t2);
  937. #endif    /* ! HAVE_FMOD */
  938.         break;
  939.  
  940.     case Node_assign_plus:
  941.         *lhs = make_number(lval + rval);
  942.         break;
  943.  
  944.     case Node_assign_minus:
  945.         *lhs = make_number(lval - rval);
  946.         break;
  947.     default:
  948.         cant_happen();
  949.     }
  950.     tree->lnode->flags |= SCALAR;
  951.     if (after_assign)
  952.         (*after_assign)();
  953.     return *lhs;
  954. }
  955.  
  956. /* func_call --- call a function, call by reference for arrays */
  957.  
  958. NODE **stack_ptr;
  959.  
  960. static NODE *
  961. func_call(name, arg_list)
  962. NODE *name;        /* name is a Node_val giving function name */
  963. NODE *arg_list;        /* Node_expression_list of calling args. */
  964. {
  965.     register NODE *arg, *argp, *r;
  966.     NODE *n, *f;
  967.     jmp_buf volatile func_tag_stack;
  968.     jmp_buf volatile loop_tag_stack;
  969.     int volatile save_loop_tag_valid = FALSE;
  970.     NODE **volatile save_stack, *save_ret_node;
  971.     NODE **volatile local_stack = NULL, **sp;
  972.     int count;
  973.     extern NODE *ret_node;
  974.  
  975.     /* retrieve function definition node */
  976.     f = lookup(name->stptr);
  977.     if (f == NULL || f->type != Node_func)
  978.         fatal("function `%s' not defined", name->stptr);
  979. #ifdef FUNC_TRACE
  980.     fprintf(stderr, "function %s called\n", name->stptr);
  981. #endif
  982.     count = f->lnode->param_cnt;
  983.     if (count > 0)
  984.         emalloc(local_stack, NODE **, count*sizeof(NODE *), "func_call");
  985.     sp = local_stack;
  986.  
  987.     /* for each calling arg. add NODE * on stack */
  988.     for (argp = arg_list; count > 0 && argp != NULL; argp = argp->rnode) {
  989.         arg = argp->lnode;
  990.         getnode(r);
  991.         r->type = Node_var;
  992.  
  993.         /* call by reference for arrays; see below also */
  994.         if (arg->type == Node_param_list)
  995.             arg = stack_ptr[arg->param_cnt];
  996.         if (arg->type == Node_var_array)
  997.             *r = *arg;
  998.         else {
  999.             n = tree_eval(arg);
  1000.             r->lnode = dupnode(n);
  1001.             r->rnode = (NODE *) NULL;
  1002.               if ((n->flags & SCALAR) != 0)
  1003.                   r->flags |= SCALAR;
  1004.             free_temp(n);
  1005.           }
  1006.         *sp++ = r;
  1007.         count--;
  1008.     }
  1009.     if (argp != NULL)    /* left over calling args. */
  1010.         warning(
  1011.             "function `%s' called with more arguments than declared",
  1012.             name->stptr);
  1013.  
  1014.     /* add remaining params. on stack with null value */
  1015.     while (count-- > 0) {
  1016.         getnode(r);
  1017.         r->type = Node_var;
  1018.         r->lnode = Nnull_string;
  1019.         r->flags &= ~SCALAR;
  1020.         r->rnode = (NODE *) NULL;
  1021.         *sp++ = r;
  1022.     }
  1023.  
  1024.     /*
  1025.      * Execute function body, saving context, as a return statement
  1026.      * will longjmp back here.
  1027.      *
  1028.      * Have to save and restore the loop_tag stuff so that a return
  1029.      * inside a loop in a function body doesn't scrog any loops going
  1030.      * on in the main program.  We save the necessary info in variables
  1031.      * local to this function so that function nesting works OK.
  1032.      * We also only bother to save the loop stuff if we're in a loop
  1033.      * when the function is called.
  1034.      */
  1035.     if (loop_tag_valid) {
  1036.         int junk = 0;
  1037.  
  1038.         save_loop_tag_valid = (volatile int) loop_tag_valid;
  1039.         PUSH_BINDING(loop_tag_stack, loop_tag, junk);
  1040.         loop_tag_valid = FALSE;
  1041.     }
  1042.     save_stack = stack_ptr;
  1043.     stack_ptr = local_stack;
  1044.     PUSH_BINDING(func_tag_stack, func_tag, func_tag_valid);
  1045.     save_ret_node = ret_node;
  1046.     ret_node = Nnull_string;    /* default return value */
  1047.     if (setjmp(func_tag) == 0)
  1048.         (void) interpret(f->rnode);
  1049.  
  1050.     r = ret_node;
  1051.     ret_node = (NODE *) save_ret_node;
  1052.     RESTORE_BINDING(func_tag_stack, func_tag, func_tag_valid);
  1053.     stack_ptr = (NODE **) save_stack;
  1054.  
  1055.     /*
  1056.      * here, we pop each parameter and check whether
  1057.      * it was an array.  If so, and if the arg. passed in was
  1058.      * a simple variable, then the value should be copied back.
  1059.      * This achieves "call-by-reference" for arrays.
  1060.      */
  1061.     sp = local_stack;
  1062.     count = f->lnode->param_cnt;
  1063.     for (argp = arg_list; count > 0 && argp != NULL; argp = argp->rnode) {
  1064.         arg = argp->lnode;
  1065.         if (arg->type == Node_param_list)
  1066.             arg = stack_ptr[arg->param_cnt];
  1067.         n = *sp++;
  1068.         if ((arg->type == Node_var || arg->type == Node_var_array)
  1069.             && n->type == Node_var_array) {
  1070.             /* should we free arg->var_value ? */
  1071.             arg->var_array = n->var_array;
  1072.             arg->type = Node_var_array;
  1073.             arg->array_size = n->array_size;
  1074.             arg->table_size = n->table_size;
  1075.             arg->flags = n->flags;
  1076.         }
  1077.         /* n->lnode overlays the array size, don't unref it if array */
  1078.         if (n->type != Node_var_array)
  1079.             unref(n->lnode);
  1080.         freenode(n);
  1081.         count--;
  1082.     }
  1083.     while (count-- > 0) {
  1084.         n = *sp++;
  1085.         /* if n is a local array, all the elements should be freed */
  1086.         if (n->type == Node_var_array)
  1087.             assoc_clear(n);
  1088.         unref(n->lnode);
  1089.         freenode(n);
  1090.     }
  1091.     if (local_stack)
  1092.         free((char *) local_stack);
  1093.  
  1094.     /* Restore the loop_tag stuff if necessary. */
  1095.     if (save_loop_tag_valid) {
  1096.         int junk = 0;
  1097.  
  1098.         loop_tag_valid = (int) save_loop_tag_valid;
  1099.         RESTORE_BINDING(loop_tag_stack, loop_tag, junk);
  1100.     }
  1101.  
  1102.     if ((r->flags & PERM) == 0)
  1103.         r->flags |= TEMP;
  1104.     return r;
  1105. }
  1106.  
  1107. /*
  1108.  * r_get_lhs:
  1109.  * This returns a POINTER to a node pointer. get_lhs(ptr) is the current
  1110.  * value of the var, or where to store the var's new value 
  1111.  */
  1112.  
  1113. NODE **
  1114. r_get_lhs(ptr, assign)
  1115. register NODE *ptr;
  1116. Func_ptr *assign;
  1117. {
  1118.     register NODE **aptr = NULL;
  1119.     register NODE *n;
  1120.  
  1121.     if (ptr->type == Node_param_list)
  1122.         ptr = stack_ptr[ptr->param_cnt];
  1123.  
  1124.     switch (ptr->type) {
  1125.     case Node_var_array:
  1126.         fatal("attempt to use array `%s' in a scalar context",
  1127.             ptr->vname);
  1128.  
  1129.     case Node_var:
  1130.         aptr = &(ptr->var_value);
  1131. #ifdef DEBUG
  1132.         if (ptr->var_value->stref <= 0)
  1133.             cant_happen();
  1134. #endif
  1135.         break;
  1136.  
  1137.     case Node_FIELDWIDTHS:
  1138.         aptr = &(FIELDWIDTHS_node->var_value);
  1139.         if (assign != NULL)
  1140.             *assign = set_FIELDWIDTHS;
  1141.         break;
  1142.  
  1143.     case Node_RS:
  1144.         aptr = &(RS_node->var_value);
  1145.         if (assign != NULL)
  1146.             *assign = set_RS;
  1147.         break;
  1148.  
  1149.     case Node_FS:
  1150.         aptr = &(FS_node->var_value);
  1151.         if (assign != NULL)
  1152.             *assign = set_FS;
  1153.         break;
  1154.  
  1155.     case Node_FNR:
  1156.         unref(FNR_node->var_value);
  1157.         FNR_node->var_value = make_number((AWKNUM) FNR);
  1158.         aptr = &(FNR_node->var_value);
  1159.         if (assign != NULL)
  1160.             *assign = set_FNR;
  1161.         break;
  1162.  
  1163.     case Node_NR:
  1164.         unref(NR_node->var_value);
  1165.         NR_node->var_value = make_number((AWKNUM) NR);
  1166.         aptr = &(NR_node->var_value);
  1167.         if (assign != NULL)
  1168.             *assign = set_NR;
  1169.         break;
  1170.  
  1171.     case Node_NF:
  1172.         if (NF == -1)
  1173.             (void) get_field(HUGE-1, assign); /* parse record */
  1174.         unref(NF_node->var_value);
  1175.         NF_node->var_value = make_number((AWKNUM) NF);
  1176.         aptr = &(NF_node->var_value);
  1177.         if (assign != NULL)
  1178.             *assign = set_NF;
  1179.         break;
  1180.  
  1181.     case Node_IGNORECASE:
  1182.         aptr = &(IGNORECASE_node->var_value);
  1183.         if (assign != NULL)
  1184.             *assign = set_IGNORECASE;
  1185.         break;
  1186.  
  1187.     case Node_OFMT:
  1188.         aptr = &(OFMT_node->var_value);
  1189.         if (assign != NULL)
  1190.             *assign = set_OFMT;
  1191.         break;
  1192.  
  1193.     case Node_CONVFMT:
  1194.         aptr = &(CONVFMT_node->var_value);
  1195.         if (assign != NULL)
  1196.             *assign = set_CONVFMT;
  1197.         break;
  1198.  
  1199.     case Node_ORS:
  1200.         aptr = &(ORS_node->var_value);
  1201.         if (assign != NULL)
  1202.             *assign = set_ORS;
  1203.         break;
  1204.  
  1205.     case Node_OFS:
  1206.         aptr = &(OFS_node->var_value);
  1207.         if (assign != NULL)
  1208.             *assign = set_OFS;
  1209.         break;
  1210.  
  1211.     case Node_param_list:
  1212.         aptr = &(stack_ptr[ptr->param_cnt]->var_value);
  1213.         break;
  1214.  
  1215.     case Node_field_spec:
  1216.         {
  1217.         int field_num;
  1218.  
  1219.         n = tree_eval(ptr->lnode);
  1220.         field_num = (int) force_number(n);
  1221.         free_temp(n);
  1222.         if (field_num < 0)
  1223.             fatal("attempt to access field %d", field_num);
  1224.         if (field_num == 0 && field0_valid) {    /* short circuit */
  1225.             aptr = &fields_arr[0];
  1226.             if (assign != NULL)
  1227.                 *assign = reset_record;
  1228.             break;
  1229.         }
  1230.         aptr = get_field(field_num, assign);
  1231.         break;
  1232.         }
  1233.     case Node_subscript:
  1234.         n = ptr->lnode;
  1235.         if (n->type == Node_param_list) {
  1236.             int i = n->param_cnt + 1;
  1237.  
  1238.             n = stack_ptr[n->param_cnt];
  1239.             if ((n->flags & SCALAR) != 0)
  1240.                 fatal("attempt to use scalar parameter %d as an array", i);
  1241.         }
  1242.         aptr = assoc_lookup(n, concat_exp(ptr->rnode));
  1243.         break;
  1244.  
  1245.     case Node_func:
  1246.         fatal("`%s' is a function, assignment is not allowed",
  1247.             ptr->lnode->param);
  1248.     default:
  1249.         cant_happen();
  1250.     }
  1251.     return aptr;
  1252. }
  1253.  
  1254. /* match_op --- do ~ and !~ */
  1255.  
  1256. static NODE *
  1257. match_op(tree)
  1258. register NODE *tree;
  1259. {
  1260.     register NODE *t1;
  1261.     register Regexp *rp;
  1262.     int i;
  1263.     int match = TRUE;
  1264.     int kludge_need_start = FALSE;    /* XXX --- see below */
  1265.  
  1266.     if (tree->type == Node_nomatch)
  1267.         match = FALSE;
  1268.     if (tree->type == Node_regex)
  1269.         t1 = *get_field(0, (Func_ptr *) 0);
  1270.     else {
  1271.         t1 = force_string(tree_eval(tree->lnode));
  1272.         tree = tree->rnode;
  1273.     }
  1274.     rp = re_update(tree);
  1275.     /*
  1276.      * XXX
  1277.      *
  1278.      * Any place where research() is called with a last parameter of
  1279.      * FALSE, we need to use the avoid_dfa test. This is the only place
  1280.      * at the moment.
  1281.      *
  1282.      * A new or improved dfa that distinguishes beginning/end of
  1283.      * string from beginning/end of line will allow us to get rid of
  1284.      * this temporary hack.
  1285.      *
  1286.      * The avoid_dfa() function is in re.c; it is not very smart.
  1287.      */
  1288.     if (avoid_dfa(tree, t1->stptr, t1->stlen))
  1289.         kludge_need_start = TRUE;
  1290.     i = research(rp, t1->stptr, 0, t1->stlen, kludge_need_start);
  1291.     i = (i == -1) ^ (match == TRUE);
  1292.     free_temp(t1);
  1293.     return tmp_number((AWKNUM) i);
  1294. }
  1295.  
  1296. /* set_IGNORECASE --- update IGNORECASE as appropriate */
  1297.  
  1298. void
  1299. set_IGNORECASE()
  1300. {
  1301.     static int warned = FALSE;
  1302.  
  1303.     if ((do_lint || do_traditional) && ! warned) {
  1304.         warned = TRUE;
  1305.         warning("IGNORECASE not supported in compatibility mode");
  1306.     }
  1307.     if (do_traditional)
  1308.         IGNORECASE = FALSE;
  1309.     else if (IGNORECASE_node->var_value->flags & STRING)
  1310.         IGNORECASE = (force_string(IGNORECASE_node->var_value)->stlen > 0);
  1311.     else if (IGNORECASE_node->var_value->flags & NUMBER)
  1312.         IGNORECASE = (force_number(IGNORECASE_node->var_value) != 0.0);
  1313.     else
  1314.         IGNORECASE = FALSE;        /* shouldn't happen */
  1315.     set_FS_if_not_FIELDWIDTHS();
  1316. }
  1317.  
  1318. /* set_OFS --- update OFS related variables when OFS assigned to */
  1319.  
  1320. void
  1321. set_OFS()
  1322. {
  1323.     OFS = force_string(OFS_node->var_value)->stptr;
  1324.     OFSlen = OFS_node->var_value->stlen;
  1325.     OFS[OFSlen] = '\0';
  1326. }
  1327.  
  1328. /* set_ORS --- update ORS related variables when ORS assigned to */
  1329.  
  1330. void
  1331. set_ORS()
  1332. {
  1333.     ORS = force_string(ORS_node->var_value)->stptr;
  1334.     ORSlen = ORS_node->var_value->stlen;
  1335.     ORS[ORSlen] = '\0';
  1336. }
  1337.  
  1338. /* fmt_ok --- is the conversion format a valid one? */
  1339.  
  1340. NODE **fmt_list = NULL;
  1341. static int fmt_ok P((NODE *n));
  1342. static int fmt_index P((NODE *n));
  1343.  
  1344. static int
  1345. fmt_ok(n)
  1346. NODE *n;
  1347. {
  1348.     NODE *tmp = force_string(n);
  1349.     char *p = tmp->stptr;
  1350.  
  1351.     if (*p++ != '%')
  1352.         return 0;
  1353.     while (*p && strchr(" +-#", *p) != NULL)    /* flags */
  1354.         p++;
  1355.     while (*p && isdigit(*p))    /* width - %*.*g is NOT allowed */
  1356.         p++;
  1357.     if (*p == '\0' || (*p != '.' && ! isdigit(*p)))
  1358.         return 0;
  1359.     if (*p == '.')
  1360.         p++;
  1361.     while (*p && isdigit(*p))    /* precision */
  1362.         p++;
  1363.     if (*p == '\0' || strchr("efgEG", *p) == NULL)
  1364.         return 0;
  1365.     if (*++p != '\0')
  1366.         return 0;
  1367.     return 1;
  1368. }
  1369.  
  1370. /* fmt_index --- track values of OFMT and CONVFMT to keep semantics correct */
  1371.  
  1372. static int
  1373. fmt_index(n)
  1374. NODE *n;
  1375. {
  1376.     register int ix = 0;
  1377.     static int fmt_num = 4;
  1378.     static int fmt_hiwater = 0;
  1379.  
  1380.     if (fmt_list == NULL)
  1381.         emalloc(fmt_list, NODE **, fmt_num*sizeof(*fmt_list), "fmt_index");
  1382.     (void) force_string(n);
  1383.     while (ix < fmt_hiwater) {
  1384.         if (cmp_nodes(fmt_list[ix], n) == 0)
  1385.             return ix;
  1386.         ix++;
  1387.     }
  1388.     /* not found */
  1389.     n->stptr[n->stlen] = '\0';
  1390.     if (do_lint && ! fmt_ok(n))
  1391.         warning("bad %sFMT specification",
  1392.                 n == CONVFMT_node->var_value ? "CONV"
  1393.               : n == OFMT_node->var_value ? "O"
  1394.               : "");
  1395.  
  1396.     if (fmt_hiwater >= fmt_num) {
  1397.         fmt_num *= 2;
  1398.         emalloc(fmt_list, NODE **, fmt_num, "fmt_index");
  1399.     }
  1400.     fmt_list[fmt_hiwater] = dupnode(n);
  1401.     return fmt_hiwater++;
  1402. }
  1403.  
  1404. /* set_OFMT --- track OFMT correctly */
  1405.  
  1406. void
  1407. set_OFMT()
  1408. {
  1409.     OFMTidx = fmt_index(OFMT_node->var_value);
  1410.     OFMT = fmt_list[OFMTidx]->stptr;
  1411. }
  1412.  
  1413. /* set_CONVFMT --- track CONVFMT correctly */
  1414.  
  1415. void
  1416. set_CONVFMT()
  1417. {
  1418.     CONVFMTidx = fmt_index(CONVFMT_node->var_value);
  1419.     CONVFMT = fmt_list[CONVFMTidx]->stptr;
  1420. }
  1421.